home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK2.toast / Development Kits (Disc 2) / QuickTime / Programming Stuff / Sample Code / Media Handlers / TimeCode / TimeCode Samples / AddTimeCodeƒ / AddTC.c next >
Encoding:
C/C++ Source or Header  |  1994-12-07  |  13.7 KB  |  546 lines  |  [TEXT/MPS ]

  1. /*
  2.   File:            AddTC.c
  3.   Contains:        Time Code Functions.
  4.   Written by:    QT Engineering
  5.   Copyright:    © 1991-1994 by Apple Computer, Inc., all rights reserved.
  6.   Change History (most recent first):
  7.   <1>         12/7/94        khs        changed the format of the file to the new look and feel
  8.   To Do:
  9. */
  10.  
  11.  
  12. // INCLUDES
  13. #include <errors.h>
  14. #include <memory.h>
  15. #include <qdoffscreen.h>
  16. #include <palettes.h>
  17. #include <resources.h>
  18. #include <toolutils.h>
  19. #include <osutils.h>
  20. #include <files.h>
  21. #include <desk.h>
  22. #include <events.h>
  23. #include <osevents.h>
  24. #include <menus.h>
  25. #include <timer.h>
  26. #include <gestaltequ.h>
  27. #include <string.h>
  28. #include <strings.h>
  29. #include <fonts.h>
  30. #include <dialogs.h>
  31. #include <QuickDrawText.h>
  32.  
  33. #include <stdio.h>
  34.  
  35. #include <Components.h>
  36. #include <Movies.h>
  37. #include <QuickTimeComponents.h>
  38.  
  39.  
  40. // GLOBALS
  41. Str255 tcSrcName;
  42. Boolean tcDisplayTimeCode = false;
  43. Boolean tcDisplayBelowVideo = true;
  44. TimeScale tcTimeScale = 2997;
  45. TimeValue tcFrameDur = 100;
  46. long tcNumFrames = 30;
  47. Boolean tcDropFrameVal = true;
  48. Boolean tc24Hour = true;
  49. Boolean tcNegOK = false;
  50. Boolean tcIsNeg = false;
  51. long tcHours = 0;
  52. long tcMinutes = 0;
  53. long tcSeconds = 0;
  54. long tcFrames = 0;
  55. long tcCounterVal = 0;
  56. Boolean tcUseTimeCode = true;
  57.  
  58.  
  59. // FUNCTION PROTOTYPES
  60. extern OSErr    GetMovie(Movie *theOutMovie, short *refnum, short *resid);
  61. extern OSErr    InitEveryBody(void);
  62. extern void        main(void);
  63. extern void        AddTimeCode(Movie theMovie);
  64. extern void        DeleteTimeCodes(Movie theMovie);
  65. extern Boolean    GetTimeCodeOptions(void);
  66. extern void        setDialogTextNumber(DialogPtr d, short itemNumber, long number);
  67. extern void        setDialogTextString(DialogPtr d, short itemNumber, StringPtr str);
  68. extern Boolean    validateDialogLong(DialogPtr d, short itemNumber, long *result);
  69. ControlHandle getDItemHandle(DialogPtr d, short itemNumber);
  70. ControlHandle getDItemRect(DialogPtr d, short itemNumber, Rect *r);
  71.  
  72.  
  73. // FUNCTIONS
  74. OSErr GetMovie(Movie *theOutMovie, short *refnum, short *resid)
  75. {
  76.     SFTypeList    typeList;
  77.     StandardFileReply reply;
  78.     OSErr        result = noErr;
  79.     Movie        theMovie = nil;
  80.     
  81.     typeList[0] = 'MooV';
  82.     StandardGetFile(nil, 1, typeList, &reply);
  83.     if (!reply.sfGood) goto bail;
  84.  
  85.     result = OpenMovieFile(&reply.sfFile, refnum, 0);
  86.     if (result != noErr) goto bail;
  87.     *resid = 0;
  88.     
  89.     result = NewMovieFromFile(&theMovie,*refnum, resid, nil,0, nil);
  90.     if (result != noErr) goto bail;
  91.  
  92. bail:
  93.     if (result) {
  94.         DisposeMovie(theMovie);
  95.         if (*refnum) CloseMovieFile(*refnum);
  96.         *theOutMovie = nil;
  97.         }
  98.     else
  99.         *theOutMovie = theMovie;
  100.     return result;
  101. }
  102.  
  103.  
  104. OSErr InitEveryBody(void)
  105. {
  106.     InitGraf(&qd.thePort);
  107.     InitFonts();
  108.     FlushEvents(0xffff,0);
  109.     InitWindows();
  110.     InitMenus();
  111.     InitDialogs(0);
  112.     TEInit();
  113.     InitCursor();
  114.  
  115.  
  116.     return EnterMovies();
  117. }
  118.  
  119.  
  120. void main( void )
  121. {
  122.     OSErr err;
  123.     Movie theMovie;
  124.     short movieResRef;
  125.     short movieResID;
  126.     
  127.     MaxApplZone();
  128.     MoreMasters();
  129.     MoreMasters();
  130.  
  131.     err = InitEveryBody();
  132.     if (err) return;
  133.     
  134.     err = GetMovie(&theMovie, &movieResRef, &movieResID );
  135.     
  136.     if (!GetTimeCodeOptions())
  137.         return;
  138.     
  139.     // delete any existing TimeCode tracks
  140.     DeleteTimeCodes( theMovie );
  141.     AddTimeCode( theMovie );    
  142.  
  143.     UpdateMovieResource( theMovie, movieResRef, movieResID, nil );
  144.     CloseMovieFile( movieResRef );
  145.  
  146. }
  147.  
  148.  
  149. #ifndef fieldOffset
  150.     #define fieldOffset(type, field) ((short) &((type *) 0)->field)
  151. #endif
  152.  
  153. void DeleteTimeCodes( Movie theMovie )
  154. {
  155.     Track theTrack;
  156.     
  157.     theTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType);
  158.     while (theTrack) {
  159.         DisposeMovieTrack( theTrack );
  160.         theTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType);
  161.         }
  162.  
  163. }
  164.  
  165. void AddTimeCode( Movie theMovie )
  166. {
  167.     OSErr err;
  168.     Track theTrack;
  169.     Media theMedia;
  170.     MediaHandler mh;
  171.     long i;
  172.     TimeCodeDef tcdef;
  173.     TimeCodeRecord tcrec;
  174.     UserData srcRef;
  175.     Str63 tcStr;
  176.     TimeValue movieDur;
  177.     Rect curMovieBox;
  178.     MatrixRecord mr;
  179.     Fixed fwidth;
  180.     Fixed fheight;
  181.     long startingTrackCount;
  182.     long flags;
  183.     
  184.     // calculate track height based on text
  185.     
  186.     TCTextOptions textOptions;
  187.     FontInfo fontInfo;
  188.     
  189.     startingTrackCount = GetMovieTrackCount( theMovie );
  190.     
  191.     GetMovieBox( theMovie, &curMovieBox );
  192.     OffsetRect( &curMovieBox, -curMovieBox.left, -curMovieBox.top );
  193.     
  194.     theTrack = NewMovieTrack( theMovie, 20, 20, 0);        // random track height
  195.     theMedia = NewTrackMedia( theTrack, TimeCodeMediaType, GetMovieTimeScale(theMovie), nil, 0 );
  196.     mh = GetMediaHandler( theMedia );
  197.     
  198.     // get display options to calc box height
  199.     TCGetDisplayOptions( mh, &textOptions );
  200.     
  201.     if (!tcUseTimeCode) {
  202.         flags = tcCounter;
  203.         }
  204.     else {
  205.         flags = 0;
  206.         if (tcDropFrameVal) flags |= tcDropFrame;
  207.         if (tcIsNeg) flags |= tcNegTimesOK;
  208.         if (tc24Hour) flags |= tc24HourMax;
  209.         }
  210.     tcdef.flags = flags;
  211.     tcdef.fTimeScale = tcTimeScale;
  212.     tcdef.frameDuration = tcFrameDur;
  213.     tcdef.numFrames = tcNumFrames;
  214.  
  215.     if (!tcUseTimeCode) {
  216.         tcrec.c.counter = tcCounterVal;
  217.         }
  218.     else {
  219.         tcrec.t.hours = tcHours;
  220.         tcrec.t.minutes = tcMinutes;        // negative flag is here
  221.         tcrec.t.seconds = tcSeconds;
  222.         tcrec.t.frames = tcFrames;
  223.         if (tcIsNeg) tcrec.t.minutes |= tctNegFlag;
  224.         }
  225.  
  226.     // use starting time to figure out dimensions of track
  227.     
  228.     err = TCTimeCodeToString( mh, &tcdef, &tcrec, tcStr);
  229.     TextFont( textOptions.txFont );
  230.     TextFace( textOptions.txFace );
  231.     TextSize( textOptions.txSize );
  232.     GetFontInfo(&fontInfo);
  233.     
  234.     fheight = (long)(fontInfo.ascent + fontInfo.descent + 2)<<16;
  235.     fwidth = (long)(StringWidth(tcStr) + 4)<<16;
  236.     
  237.     GetTrackMatrix( theTrack, &mr );
  238.     if (tcDisplayBelowVideo) {
  239.         fwidth = (long)(curMovieBox.right - curMovieBox.left) << 16;
  240.         SetTrackDimensions( theTrack, fwidth, fheight );
  241.         TranslateMatrix( &mr, 0, ((long)curMovieBox.bottom) << 16 );
  242.         }
  243.     else {
  244.         SetTrackDimensions( theTrack, fwidth, fheight );
  245.         TranslateMatrix( &mr, (Fixed)(curMovieBox.left + ((curMovieBox.right - curMovieBox.left - (fwidth>>16))>>1))<<16, 
  246.                 (Fixed)(curMovieBox.bottom - (((fheight + (fheight>>1)) >> 16))) << 16 );
  247.         }
  248.     SetTrackMatrix( theTrack, &mr );
  249.     
  250.     SetTrackEnabled( theTrack, tcDisplayTimeCode?true:false );
  251.     TCSetTimeCodeFlags( mh, tcDisplayTimeCode?tcdfShowTimeCode:0, tcdfShowTimeCode );
  252.     
  253.     err = BeginMediaEdits( theMedia );
  254.     
  255.     {
  256.     TimeCodeDescriptionHandle tcdH;
  257.     long **frameH;
  258.     long size;
  259.     Handle nameH;
  260.     
  261.     size = fieldOffset(TimeCodeDescription, srcRef);
  262.     tcdH = (TimeCodeDescriptionHandle) NewHandleClear( size );
  263.     (**tcdH).descSize = size;
  264.     (**tcdH).dataFormat = TimeCodeMediaType;
  265.     (**tcdH).timeCodeDef = tcdef;
  266.     
  267.     err = NewUserData( &srcRef );
  268.     err = PtrToHand( &tcSrcName[1], &nameH, tcSrcName[0] );
  269.     err = AddUserDataText( srcRef, nameH, 'name', 1, langEnglish );
  270.     TCSetSourceRef( mh, tcdH, srcRef );
  271.     
  272.     frameH = (long**)NewHandle( sizeof(long) );
  273.     
  274.     err = TCTimeCodeToFrameNumber( mh, 
  275.                 &(**tcdH).timeCodeDef, &tcrec, *frameH );
  276.     
  277.     movieDur = GetMovieDuration(theMovie);
  278.     // Since we created the track with the same timescale as the movie,
  279.     // we don't need to convert the duration
  280.     
  281.     err = AddMediaSample( theMedia, (Handle)frameH, 0, GetHandleSize((Handle)frameH),
  282.         movieDur,
  283.         (SampleDescriptionHandle)tcdH, 
  284.         1, 0, 0 );
  285.         
  286.     DisposeHandle( (Handle) tcdH );
  287.     DisposeHandle( (Handle) frameH );
  288.     DisposeHandle( nameH );
  289.     DisposeUserData( srcRef );
  290.     }
  291.     
  292.     err = EndMediaEdits( theMedia );    
  293.  
  294.     err = InsertMediaIntoTrack( theTrack, 0, 0, movieDur, fixed1 );
  295.     
  296.     // let's record that this is timecode for all the current tracks
  297.     for (i = 1; i <= startingTrackCount; i++) {
  298.         err = AddTrackReference(GetMovieIndTrack(theMovie, i ), theTrack, TimeCodeMediaType, nil);
  299.     }
  300. }
  301.  
  302. #define diDialog 128
  303.  
  304. #define diSrcName 4
  305. #define diDisplayTimeCode 5
  306. #define diTimeScale 7
  307. #define diFrameDur 9
  308. #define diNumFrames 11
  309.  
  310. #define diUseTC 12
  311. #define diUseCounter 13
  312.  
  313. #define diDropFrame 14
  314. #define di24Hour (diDropFrame + 1)
  315. #define diNegOK (di24Hour + 1)
  316. #define diIsNeg (diNegOK + 2)
  317. #define diHours (diIsNeg + 1)
  318. #define diMinutes (diHours + 1)
  319. #define diSeconds (diMinutes + 1)
  320. #define diFrames (diSeconds + 1)
  321.  
  322. #define diCounter 24
  323. #define diBelowVideo 25
  324.  
  325. Boolean GetTimeCodeOptions(void)
  326. {
  327.     DialogPtr optionsDialog = nil;
  328.     short itemHit = cancel;
  329.     ControlHandle curCtl;
  330.     Rect negRect;
  331.     GrafPtr curPort;
  332.     
  333.     GetPort(&curPort);
  334.     
  335.     optionsDialog = GetNewDialog( diDialog, nil, (WindowPtr)-1L );
  336.     if (!optionsDialog) goto bail;
  337.     
  338.     SetDialogDefaultItem(optionsDialog, 1);
  339.     SetDialogCancelItem(optionsDialog, 2);
  340.  
  341.     curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode );
  342.     SetCtlValue(curCtl,tcDisplayTimeCode);
  343.     curCtl = getDItemHandle( optionsDialog, diBelowVideo );
  344.     SetCtlValue(curCtl,tcDisplayBelowVideo);
  345.     curCtl = getDItemHandle( optionsDialog, diDropFrame );
  346.     SetCtlValue(curCtl,tcDropFrameVal);
  347.     curCtl = getDItemHandle( optionsDialog, di24Hour );
  348.     SetCtlValue(curCtl,tc24Hour);
  349.     curCtl = getDItemHandle( optionsDialog, diNegOK );
  350.     SetCtlValue(curCtl,tcNegOK);
  351.     curCtl = getDItemRect( optionsDialog, diIsNeg, &negRect );
  352.     SetPort(optionsDialog);
  353.     MoveTo(negRect.left+2, negRect.top+17);
  354.     FrameRect(&negRect);
  355.     TextSize(20);
  356.     if (tcIsNeg) 
  357.         DrawString("\p-");
  358.     else
  359.         DrawString("\p+");
  360.     TextSize(12);
  361.  
  362.     curCtl = getDItemHandle( optionsDialog, diUseTC );
  363.     SetCtlValue(curCtl,tcUseTimeCode?1:0);
  364.     curCtl = getDItemHandle( optionsDialog, diUseCounter );
  365.     SetCtlValue(curCtl,tcUseTimeCode?0:1);
  366.  
  367.     setDialogTextNumber(optionsDialog, diTimeScale, tcTimeScale );
  368.     setDialogTextNumber(optionsDialog, diFrameDur, tcFrameDur );
  369.     setDialogTextNumber(optionsDialog, diNumFrames, tcNumFrames );
  370.     setDialogTextNumber(optionsDialog, diHours, tcHours );
  371.     setDialogTextNumber(optionsDialog, diMinutes, tcMinutes );
  372.     setDialogTextNumber(optionsDialog, diSeconds, tcSeconds );
  373.     setDialogTextNumber(optionsDialog, diFrames, tcFrames );
  374.  
  375.     setDialogTextNumber(optionsDialog, diCounter, tcCounterVal );
  376.     
  377.     setDialogTextString(optionsDialog, diSrcName, tcSrcName);
  378.  
  379. noGood:
  380.     do {
  381.     
  382.         ModalDialog( nil, &itemHit );
  383.         switch (itemHit) {
  384.             case diDisplayTimeCode:
  385.                 curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode );
  386.                 SetCtlValue(curCtl,!GetCtlValue(curCtl));
  387.                 break;
  388.             case diBelowVideo:
  389.                 curCtl = getDItemHandle( optionsDialog, diBelowVideo );
  390.                 SetCtlValue(curCtl,!GetCtlValue(curCtl));
  391.                 break;
  392.             case diDropFrame:
  393.                 curCtl = getDItemHandle( optionsDialog, diDropFrame );
  394.                 SetCtlValue(curCtl,!GetCtlValue(curCtl));
  395.                 break;
  396.             case di24Hour:
  397.                 curCtl = getDItemHandle( optionsDialog, di24Hour );
  398.                 SetCtlValue(curCtl,!GetCtlValue(curCtl));
  399.                 break;
  400.             case diNegOK:
  401.                 curCtl = getDItemHandle( optionsDialog, diNegOK );
  402.                 SetCtlValue(curCtl,!GetCtlValue(curCtl));
  403.                 break;
  404.             case diUseTC:
  405.                 curCtl = getDItemHandle( optionsDialog, diUseTC );
  406.                 SetCtlValue(curCtl,1);
  407.                 curCtl = getDItemHandle( optionsDialog, diUseCounter );
  408.                 SetCtlValue(curCtl,0);
  409.                 break;
  410.             case diUseCounter:
  411.                 curCtl = getDItemHandle( optionsDialog, diUseCounter );
  412.                 SetCtlValue(curCtl,1);
  413.                 curCtl = getDItemHandle( optionsDialog, diUseTC );
  414.                 SetCtlValue(curCtl,0);
  415.                 break;
  416.             case diIsNeg:
  417.                 tcIsNeg = !tcIsNeg;
  418.                 SetPort(optionsDialog);
  419.     MoveTo(negRect.left+2, negRect.top+17);
  420.                 FrameRect(&negRect);
  421.                 InsetRect(&negRect,1,1);
  422.                 EraseRect(&negRect);
  423.                 InsetRect(&negRect,-1,-1);
  424.                 TextSize(20);
  425.                 if (tcIsNeg) 
  426.                     DrawString("\p-");
  427.                 else
  428.                     DrawString("\p+");
  429.                 TextSize(12);
  430.                 break;
  431.             }
  432.     } while ((itemHit != ok) && (itemHit != cancel));
  433.     
  434.     if (itemHit == ok) {
  435.         curCtl = getDItemHandle(optionsDialog, diSrcName);
  436.         GetIText((Handle)curCtl, tcSrcName);
  437.     
  438.         curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode );
  439.         tcDisplayTimeCode = GetCtlValue(curCtl);
  440.         curCtl = getDItemHandle( optionsDialog, diBelowVideo );
  441.         tcDisplayBelowVideo = GetCtlValue(curCtl);
  442.         curCtl = getDItemHandle( optionsDialog, diDropFrame );
  443.         tcDropFrameVal = GetCtlValue(curCtl);
  444.         curCtl = getDItemHandle( optionsDialog, di24Hour );
  445.         tc24Hour = GetCtlValue(curCtl);
  446.         curCtl = getDItemHandle( optionsDialog, diNegOK );
  447.         tcNegOK = GetCtlValue(curCtl);
  448.         curCtl = getDItemHandle( optionsDialog, diUseTC );
  449.         tcUseTimeCode = (GetCtlValue(curCtl) != 0);
  450.  
  451.         if (!validateDialogLong(optionsDialog, diTimeScale, &tcTimeScale))
  452.             goto noGood;
  453.         if (!validateDialogLong(optionsDialog, diFrameDur, &tcFrameDur))
  454.             goto noGood;
  455.         if (!validateDialogLong(optionsDialog, diNumFrames, &tcNumFrames))
  456.             goto noGood;
  457.         if (!validateDialogLong(optionsDialog, diHours, &tcHours))
  458.             goto noGood;
  459.         if (!validateDialogLong(optionsDialog, diMinutes, &tcMinutes))
  460.             goto noGood;
  461.         if (!validateDialogLong(optionsDialog, diSeconds, &tcSeconds))
  462.             goto noGood;
  463.         if (!validateDialogLong(optionsDialog, diFrames, &tcFrames))
  464.             goto noGood;
  465.         if (!validateDialogLong(optionsDialog, diCounter, &tcCounterVal))
  466.             goto noGood;
  467.         }
  468.     
  469.     DisposDialog(optionsDialog);
  470. bail:
  471.     SetPort(curPort);
  472.     return (itemHit == ok);
  473. }
  474.  
  475. void setDialogTextNumber(DialogPtr d, short itemNumber, long number)
  476. {
  477.     Str255 theText;
  478.  
  479.     NumToString(number, theText);
  480.     SetIText((Handle)getDItemHandle(d, itemNumber), theText);
  481.     SelIText(d, itemNumber, 0, 32767);
  482. }
  483.  
  484.  
  485. void setDialogTextString(DialogPtr d, short itemNumber, StringPtr str)
  486. {
  487.     SetIText((Handle)getDItemHandle(d, itemNumber), str);
  488.     SelIText(d, itemNumber, 0, 32767);
  489. }
  490.  
  491. Boolean validateDialogLong(DialogPtr d, short itemNumber, long *result)
  492. {
  493.     Str255 theText;
  494.     ControlHandle ch;
  495.     Boolean digitFound;
  496.     short i;
  497.  
  498.     ch = getDItemHandle(d, itemNumber);
  499.  
  500.     GetIText((Handle)ch, theText);
  501.  
  502.     digitFound = false;
  503.     for (i = 1; i < theText[0]; i++) {
  504.         if (theText[i] >= '0' && theText[i] <= '9') 
  505.             digitFound = true;
  506.         else if (digitFound) {
  507.             theText[0] = i-1;
  508.             break;
  509.         }
  510.         else if (theText[i] != ' ') {
  511.             SelIText(d, itemNumber, 0, 32767);
  512.             SysBeep(1);
  513.             return false;
  514.         }
  515.     }
  516.  
  517.     StringToNum( theText, result );
  518.  
  519.     return true;
  520. }
  521.  
  522. ControlHandle getDItemHandle(DialogPtr d, short itemNumber)
  523. {
  524.     short kind;
  525.     ControlHandle ch;
  526.     Rect r;
  527.  
  528.     GetDItem(d, itemNumber, &kind, (Handle *)&ch, &r);
  529.  
  530.     return(ch);
  531. }
  532.  
  533. ControlHandle getDItemRect(DialogPtr d, short itemNumber, Rect *r)
  534. {
  535.     short kind;
  536.     ControlHandle ch;
  537.  
  538.     GetDItem(d, itemNumber, &kind, (Handle *)&ch, r);
  539.  
  540.     return(ch);
  541. }
  542.  
  543.  
  544.  
  545.  
  546.